using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Threading;

namespace WpfApp_ChenxiConsole.UDP
{
    /// <summary>
    /// UDP管理器，负责处理UDP的单播、组播和广播功能
    /// </summary>
    public class UdpManager
    {
        private UdpClient? udpClient;
        private bool isReceiving = false;
        private Action<string, string>? onMessageReceived; // 回调函数，用于通知接收到的消息
        private Action<Brush>? onUpdateLinkPointerColor; // 回调函数，用于更新连接状态指示器颜色
        private Dispatcher? dispatcher; // UI线程的Dispatcher
        private string? multicastGroupIP; // 组播组IP地址
        private int localPort; // 本地监听端口

        /// <summary>
        /// 初始化UdpManager
        /// </summary>
        /// <param name="dispatcher">UI线程的Dispatcher</param>
        /// <param name="onMessageReceived">消息接收回调函数</param>
        /// <param name="onUpdateLinkPointerColor">更新连接状态指示器颜色的回调函数</param>
        public UdpManager(
            Dispatcher dispatcher,
            Action<string, string> onMessageReceived,
            Action<Brush> onUpdateLinkPointerColor
        )
        {
            this.dispatcher = dispatcher;
            this.onMessageReceived = onMessageReceived;
            this.onUpdateLinkPointerColor = onUpdateLinkPointerColor;
        }

        /// <summary>
        /// 初始化UDP客户端并开始监听
        /// </summary>
        /// <param name="localPort">本地监听端口</param>
        /// <returns>初始化结果</returns>
        public bool Initialize(int localPort)
        {
            try
            {
                this.localPort = localPort;
                udpClient = new UdpClient(localPort);
                
                // 更新连接状态指示器为绿色
                dispatcher?.Invoke(() =>
                {
                    onUpdateLinkPointerColor?.Invoke(Brushes.Green);
                });
                
                // 开始接收消息
                StartReceivingMessages();
                return true;
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"初始化UDP客户端错误：{ex.Message}\n", "错误");
                return false;
            }
        }

        /// <summary>
        /// 检查UDP客户端是否已初始化
        /// </summary>
        /// <returns>是否已初始化</returns>
        public bool IsInitialized()
        {
            return udpClient != null;
        }

        /// <summary>
        /// 加入组播组
        /// </summary>
        /// <param name="multicastIP">组播组IP地址</param>
        /// <returns>加入结果</returns>
        public bool JoinMulticastGroup(string multicastIP)
        {
            try
            {
                if (udpClient == null)
                {
                    onMessageReceived?.Invoke("UDP客户端未初始化\n", "错误");
                    return false;
                }

                // 保存组播组IP
                this.multicastGroupIP = multicastIP;
                IPAddress multicastAddress = IPAddress.Parse(multicastIP);
                
                // 加入组播组
                udpClient.JoinMulticastGroup(multicastAddress);
                onMessageReceived?.Invoke($"已加入组播组 {multicastIP}\n", "监听");
                return true;
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"加入组播组错误：{ex.Message}\n", "错误");
                return false;
            }
        }

        /// <summary>
        /// 离开组播组
        /// </summary>
        public void LeaveMulticastGroup()
        {
            try
            {
                if (udpClient == null || string.IsNullOrEmpty(multicastGroupIP))
                {
                    return;
                }

                IPAddress multicastAddress = IPAddress.Parse(multicastGroupIP);
                udpClient.DropMulticastGroup(multicastAddress);
                onMessageReceived?.Invoke($"已离开组播组 {multicastGroupIP}\n", "监听");
                multicastGroupIP = null;
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"离开组播组错误：{ex.Message}\n", "错误");
            }
        }

        /// <summary>
        /// 发送单播消息
        /// </summary>
        /// <param name="message">消息内容</param>
        /// <param name="remoteIP">目标IP地址</param>
        /// <param name="remotePort">目标端口</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendUnicastMessageAsync(string message, string remoteIP, int remotePort)
        {
            return await SendMessageAsync(message, remoteIP, remotePort);
        }

        /// <summary>
        /// 发送组播消息
        /// </summary>
        /// <param name="message">消息内容</param>
        /// <param name="multicastIP">组播组IP地址</param>
        /// <param name="multicastPort">组播组端口</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendMulticastMessageAsync(string message, string multicastIP, int multicastPort)
        {
            return await SendMessageAsync(message, multicastIP, multicastPort);
        }

        /// <summary>
        /// 发送广播消息
        /// </summary>
        /// <param name="message">消息内容</param>
        /// <param name="broadcastPort">广播端口</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendBroadcastMessageAsync(string message, int broadcastPort)
        {
            try
            {
                if (udpClient == null)
                {
                    onMessageReceived?.Invoke("UDP客户端未初始化\n", "错误");
                    return false;
                }

                // 启用广播
                udpClient.EnableBroadcast = true;
                
                // 发送广播消息
                bool result = await SendMessageAsync(message, "255.255.255.255", broadcastPort);
                
                // 禁用广播
                udpClient.EnableBroadcast = false;
                
                return result;
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"发送广播消息错误：{ex.Message}\n", "错误");
                return false;
            }
        }

        /// <summary>
        /// 发送UDP消息的通用方法
        /// </summary>
        /// <param name="message">消息内容</param>
        /// <param name="remoteIP">目标IP地址</param>
        /// <param name="remotePort">目标端口</param>
        /// <returns>发送结果</returns>
        private async Task<bool> SendMessageAsync(string message, string remoteIP, int remotePort)
        {
            try
            {
                if (udpClient == null)
                {
                    onMessageReceived?.Invoke("UDP客户端未初始化\n", "错误");
                    return false;
                }

                // 移除消息末尾可能存在的换行符
                message = message.TrimEnd('\r', '\n');
                
                // 将消息转换为字节数组
                byte[] data = Encoding.UTF8.GetBytes(message);
                
                // 发送消息
                await udpClient.SendAsync(data, data.Length, new IPEndPoint(IPAddress.Parse(remoteIP), remotePort));
                return true;
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"发送消息错误：{ex.Message}\n", "错误");
                return false;
            }
        }

        /// <summary>
        /// 开始接收UDP消息
        /// </summary>
        private void StartReceivingMessages()
        {
            if (udpClient == null || isReceiving)
            {
                return;
            }

            isReceiving = true;
            _ = ReceiveMessagesAsync();
        }

        /// <summary>
        /// 异步接收UDP消息
        /// </summary>
        private async Task ReceiveMessagesAsync()
        {
            try
            {
                while (udpClient != null && isReceiving)
                {
                    // 接收数据
                    UdpReceiveResult result = await udpClient.ReceiveAsync();
                    string message = Encoding.UTF8.GetString(result.Buffer);
                    IPEndPoint senderEndPoint = result.RemoteEndPoint;
                    
                    // 在UI线程上显示接收到的消息
                    dispatcher?.Invoke(() =>
                    {
                        onMessageReceived?.Invoke($"{message}", $"收<< [{senderEndPoint.Address}:{senderEndPoint.Port}]");
                    });
                }
            }
            catch (ObjectDisposedException)
            {
                // UDP客户端已被释放，忽略此异常
            }
            catch (Exception ex)
            {
                if (isReceiving) // 只在接收状态下报告错误
                {
                    dispatcher?.Invoke(() =>
                    {
                        onMessageReceived?.Invoke($"接收消息错误：{ex.Message}\n", "错误");
                    });
                    
                    // 尝试重新开始接收消息
                    await Task.Delay(1000);
                    if (isReceiving)
                    {
                        _ = ReceiveMessagesAsync();
                    }
                }
            }
        }

        /// <summary>
        /// 关闭UDP客户端并释放资源
        /// </summary>
        public void Close()
        {
            try
            {
                // 停止接收消息
                isReceiving = false;
                
                // 离开组播组
                LeaveMulticastGroup();
                
                // 关闭并释放UDP客户端
                if (udpClient != null)
                {
                    udpClient.Close();
                    udpClient = null;
                }
                
                // 更新连接状态指示器为灰色
                dispatcher?.Invoke(() =>
                {
                    onUpdateLinkPointerColor?.Invoke(Brushes.Gray);
                });
            }
            catch (Exception ex)
            {
                onMessageReceived?.Invoke($"关闭UDP客户端错误：{ex.Message}\n", "错误");
            }
        }
    }
}